package reliability.ui;

import reliability.model.GraphModel;
import reliability.model.GraphModelEvent;
import reliability.model.MinimalPathsAndSectionsMethodResults;
import reliability.model.StatisticalModelingMethodResults;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.io.File;
import java.io.PrintStream;
import java.util.Locale;

public class ResultsPanel
    extends InfoPanelComponent
    implements ActionListener
{
    private static final int TEXT_FIELD_SIZE = 22;
    private static final String RESULTS_FILENAME = "results.txt";

    FlowLayout layout;
    IntegerField numberOfTestsField;
    ResultField networkReliabilityField;
    ResultField methodAccuracyField;
    ResultField functionField;
    ResultField minimumReliabilityField;
    ResultField maximumReliabilityField;
    JButton saveResultsButton;
    StatisticalModelingMethodResults statisticalModelingMethodResults;
    MinimalPathsAndSectionsMethodResults minimalPathsAndSectionsMethodResults;

    public ResultsPanel(GraphModel graphModel)
    {
        super(graphModel);
        setPreferredSize(new Dimension(290, 405));
        setBorder(BorderFactory.createTitledBorder("Результаты"));
        layout = new FlowLayout();
        layout.setAlignment(FlowLayout.LEFT);
        setLayout(layout);

        JLabel numberOfTestsLabel = new JLabel("Количество испытаний");
        add(numberOfTestsLabel);
        numberOfTestsField = new IntegerField(model.getNumberOfTests(), TEXT_FIELD_SIZE + 1);
        numberOfTestsField.addFocusListener(this);
        add(numberOfTestsField);
        addStatisticalModelingMethodPanel();
        addSectionsMethodPanel();
        saveResultsButton = new JButton("Экспорт результатов");
        saveResultsButton.addActionListener(this);
        add(saveResultsButton);
        saveResultsButton.setVisible(false);
    }

    public void focusLost(FocusEvent focusEvent)
    {
        Object fieldValue = numberOfTestsField.getValue();
        int numberOfTests = 0;
        if (fieldValue instanceof Integer)
        {
            numberOfTests = (Integer) fieldValue;
        }
        else if (fieldValue instanceof Long)
        {
            numberOfTests = ((Long) fieldValue).intValue();
        }

        model.setNumberOfTests(numberOfTests);
    }

    public void showResults(StatisticalModelingMethodResults statisticalModelingMethodResults,
                             MinimalPathsAndSectionsMethodResults minimalPathsAndSectionsMethodResults)
    {
        this.statisticalModelingMethodResults = statisticalModelingMethodResults;
        this.minimalPathsAndSectionsMethodResults = minimalPathsAndSectionsMethodResults;
        networkReliabilityField.setText(statisticalModelingMethodResults.networkReliability.toString());
        methodAccuracyField.setText(statisticalModelingMethodResults.accuracy.toString());
        functionField.setText(statisticalModelingMethodResults.function);
        functionField.setCaretPosition(0);

        minimumReliabilityField.setText(minimalPathsAndSectionsMethodResults.minimumReliability.toString());
        maximumReliabilityField.setText(minimalPathsAndSectionsMethodResults.maximumReliability.toString());
        saveResultsButton.setVisible(true);
    }

    public void actionPerformed(ActionEvent actionEvent)
    {
        printResultsToFile(RESULTS_FILENAME);
        try
        {
            Desktop desktop = Desktop.getDesktop();
            desktop.open(new File(RESULTS_FILENAME));
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    private void printResultsToFile(String filename)
    {
        try
        {
            PrintStream printStream = new PrintStream(filename);
            printStream.println("Результаты");
            printStream.print("Количество испытаний" + '\t');
            printStream.println(model.getNumberOfTests());
            printStream.println();
            printStream.println("Метод статистического моделирования");
            printStream.print("Вероятность безотказной работы" + '\t');
            printStream.println(statisticalModelingMethodResults.networkReliability);
            printStream.print("Погрешность" + '\t');
            printStream.println(statisticalModelingMethodResults.accuracy);
            printStream.print("Функция" + '\t');
            printStream.println(statisticalModelingMethodResults.function);
            printStream.println();
            printStream.println("Метод минимальных путей и сечений");
            printStream.print("Минимальная надежность" + '\t');
            printStream.println(minimalPathsAndSectionsMethodResults.minimumReliability);
            printStream.print("Максимальная надежность" + '\t');
            printStream.println(minimalPathsAndSectionsMethodResults.maximumReliability);
            printStream.println();
            printStream.println("Минимальные пути между узлами сети");
            printStream.println(model.getMinimalPaths());
            printStream.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    private void addStatisticalModelingMethodPanel()
    {
        JPanel statisticalModelingMethodPanel = new JPanel();
        statisticalModelingMethodPanel.setPreferredSize(new Dimension(270, 170));
        statisticalModelingMethodPanel.setBorder(BorderFactory.createTitledBorder("Метод статистического моделирования"));
        statisticalModelingMethodPanel.setLayout(layout);

        JLabel networkReliabilityLabel = new JLabel("Вероятность безотказной работы");
        networkReliabilityLabel.setFont(InfoPanel.DEFAULT_FONT);
        statisticalModelingMethodPanel.add(networkReliabilityLabel);
        networkReliabilityField = new ResultField();
        statisticalModelingMethodPanel.add(networkReliabilityField);

        JLabel methodAccuracyLabel = new JLabel("Погрешность");
        methodAccuracyLabel.setFont(InfoPanel.DEFAULT_FONT);
        statisticalModelingMethodPanel.add(methodAccuracyLabel);
        methodAccuracyField = new ResultField();
        statisticalModelingMethodPanel.add(methodAccuracyField);

        JLabel functionLabel = new JLabel("Функция");
        functionLabel.setFont(InfoPanel.DEFAULT_FONT);
        statisticalModelingMethodPanel.add(functionLabel);
        functionField = new ResultField();
        statisticalModelingMethodPanel.add(functionField);

        add(statisticalModelingMethodPanel);
    }

    private void addSectionsMethodPanel()
    {
        JPanel sectionsMethodPanel = new JPanel();
        sectionsMethodPanel.setPreferredSize(new Dimension(270, 120));
        sectionsMethodPanel.setBorder(BorderFactory.createTitledBorder("Метод минимальных путей и сечений"));
        sectionsMethodPanel.setLayout(layout);

        JLabel minimumReliabilityLabel = new JLabel("Минимальная надежность");
        minimumReliabilityLabel.setFont(InfoPanel.DEFAULT_FONT);
        sectionsMethodPanel.add(minimumReliabilityLabel);
        minimumReliabilityField = new ResultField();
        sectionsMethodPanel.add(minimumReliabilityField);

        JLabel maximumReliabilityLabel = new JLabel("Максимальная надежность");
        maximumReliabilityLabel.setFont(InfoPanel.DEFAULT_FONT);
        sectionsMethodPanel.add(maximumReliabilityLabel);
        maximumReliabilityField = new ResultField();
        sectionsMethodPanel.add(maximumReliabilityField);

        add(sectionsMethodPanel);
    }

    public void graphModelChanged(GraphModelEvent event)
    {
        if (event.getId() == GraphModelEvent.GRAPH_INIT)
        {
            numberOfTestsField.setValue(model.getNumberOfTests());
        }
    }
}
